﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Bonobo.Irc
{
    internal sealed class IrcConnectionReceiveBuffer
    {
        private Byte[] _buffer;
        private Int32 _count;

        public IrcConnectionReceiveBuffer(Int32 size)
        {
            _buffer = new Byte[size];
        }

        public void BeginReadFrom(Stream stream, AsyncCallback callback)
        {
            BeginReadFrom(stream, callback, null);
        }

        public void BeginReadFrom(Stream stream, AsyncCallback callback, Object state)
        {
            stream.BeginRead(_buffer, _count, _buffer.Length - _count, callback, state);
        }

        public Int32 EndReadFrom(Stream stream, IAsyncResult ar)
        {
            var read = stream.EndRead(ar);

            if (read > 0)
            {
                _count += read;
            }

            return read;
        }

        public IEnumerable<IrcMessage> ReadMessages()
        {
            const Byte CR = 13;
            const Byte LF = 10;

            var start = 0;
            var end = 0;

            while (end < _count)
            {
                if ((_buffer[end] == CR) || (_buffer[end] == LF))
                {
                    if ((_buffer[end] == CR) && (end < _buffer.Length - 1) && (_buffer[end + 1] == LF))
                    {
                        end++;
                    }

                    IrcMessage msg;

                    if (IrcMessage.TryParseAsReadOnly(_buffer, start, (end - start), out msg))
                    {
                        yield return msg;
                    }

                    start = end + 1;
                }

                end++;
            }

            if (start < end)
            {
                var newbuffer = new Byte[_buffer.Length];
                Array.Copy(_buffer, start, newbuffer, 0, _count - start);

                _buffer = newbuffer;
                _count -= start;
            }
            else
            {
                _count = 0;
            }
        }
    }
}
